# gui/main_window_pyqtads.py
"""
雷达仿真智能体主窗口
Radar Simulation Agent Main Window with PyQtAds
"""

import sys
import os
import time
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import numpy as np
import traceback

# 导入 PyQtAds
import PyQtAds

# 导入核心组件
from gui.widgets.control_widgets import (
    MeasurementDisplayWidget,
    ControlPanelWidget
)

# 尝试导入高性能绘图组件
try:
    from gui.widgets.fast_signal_plots import (
        FastSignalPlotWidget,
        FastRangeDopplerWidget,
        is_pyqtgraph_available,
        get_performance_info
    )
    FAST_PLOTS_AVAILABLE = True
    print("高性能绘图组件可用")
except ImportError as e:
    print(f"高性能绘图组件导入失败: {e}")
    FAST_PLOTS_AVAILABLE = False
from gui.widgets.chat_widget import ChatPanel
from gui.widgets.status_widget import CompactStatusBar
from gui.worker_threads import WorkerThreadManager
from simulator.simulation_process import SimulationProcess
from gui.chat_agent import GUIChatAgent
from gui.styles.style_manager import style_manager
from simulator.sim_engine import SimEngine, Target
from simulator.radar_moni import RadarSignalProcessor
from simulator.sim_controller import SimController

class RadarSimulationPyQtAdsWindow(QMainWindow):
    """雷达仿真智能体主窗口"""

    # 定义信号用于跨线程调用
    simulation_start_requested = pyqtSignal()  # 仿真启动请求信号
    simulation_stop_requested = pyqtSignal()   # 仿真停止请求信号

    def __init__(self):
        super().__init__()
        self.setObjectName("RadarSimulationPyQtAdsWindow")

        # 加载应用程序图标
        icon_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'icons', 'radar_icon.ico')
        if os.path.exists(icon_path):
            self.setWindowIcon(QIcon(icon_path))
        else:
            print(f"WARNING: 图标文件不存在: {icon_path}")

        # 初始化核心组件
        self.radar_engine = SimEngine()
        # 信号处理器现在通过回波处理器访问
        self.signal_processor = None
        self.target_counter = 0

        # 创建配置管理器
        from config.config_manager import ConfigManager
        self.config_manager = ConfigManager("radar_config.json")

        # 创建仿真控制器用于聊天集成
        self.sim_controller = SimController("logs/gui_chat.log")
        self.sim_controller.sim_engine = self.radar_engine

        # 创建仿真进程（多进程架构，彻底消除GIL竞争）
        self.sim_process = SimulationProcess(self.radar_engine)

        # 将仿真进程引用设置到控制器中
        self.sim_controller.sim_process = self.sim_process

        # 设置仿真启动/停止回调（使用信号发射，支持跨线程）
        self.sim_controller.on_simulation_started = lambda: self.simulation_start_requested.emit()
        self.sim_controller.on_simulation_stopped = lambda: self.simulation_stop_requested.emit()

        # 连接信号到槽（在主线程中执行）
        self.simulation_start_requested.connect(self._on_chat_simulation_started)
        self.simulation_stop_requested.connect(self._on_chat_simulation_stopped)

        # 创建聊天智能体
        self.chat_agent = GUIChatAgent(self.sim_controller)

        # 保留线程管理器用于聊天功能（不用于仿真）
        self.thread_manager = WorkerThreadManager(
            self.radar_engine,
            None,  # 信号处理器将在需要时从回波处理器获取
            self.chat_agent
        )
        
        
        self.init_ui()
        self.setup_timer()
        self.setup_worker_connections()
        self.setup_default_scenario()

    def get_signal_processor(self):
        """获取信号处理器实例"""
        if hasattr(self.radar_engine, 'echo_processor'):
            return self.radar_engine.echo_processor.get_signal_processor()
        else:
            # 如果还没有回波处理器，创建一个临时的信号处理器
            from simulator.radar_moni import RadarSignalProcessor
            return RadarSignalProcessor(self.radar_engine.params)
        
    def init_ui(self):
        """初始化用户界面"""
        self.setWindowTitle("雷达仿真智能体")

        # 设置程序图标
        try:
            icon_path = os.path.join(os.getcwd(), "icons", "radar_icon.ico")
            if os.path.exists(icon_path):
                self.setWindowIcon(QIcon(icon_path))
            else:
                # 备用PNG图标
                png_icon_path = os.path.join(os.getcwd(), "icons", "radar_icon.png")
                if os.path.exists(png_icon_path):
                    self.setWindowIcon(QIcon(png_icon_path))
        except Exception as e:
            print(f"设置程序图标失败: {e}")
        
        # 设置窗口初始大小和位置
        desktop = QApplication.desktop()
        available_geometry = desktop.availableGeometry()
        
        width = int(available_geometry.width() * 0.9)
        height = int(available_geometry.height() * 0.9)
        x = available_geometry.x() + (available_geometry.width() - width) // 2
        y = available_geometry.y() + (available_geometry.height() - height) // 2
        
        self.setGeometry(x, y, width, height)
        self.setMinimumSize(1200, 800)
        
        # 创建 PyQtAds DockManager
        self.dock_manager = PyQtAds.ads.CDockManager(self)

        # 加载外部样式
        self.setStyleSheet(style_manager.get_style("main_window"))
        
        # 创建dock widgets
        self.create_dock_widgets()

        # 显示绘图性能信息
        self.display_plotting_performance_info()
        
        # 全局样式已在应用程序级别设置，无需重复设置
        
        # 连接信号（保持原有功能）
        self.connect_control_signals()
        
        # 创建状态栏
        self.compact_status_bar = CompactStatusBar()
        self.statusBar().addPermanentWidget(self.compact_status_bar)
        self.statusBar().showMessage("雷达仿真系统就绪")
        
        # 创建菜单栏
        self.create_menus()
        
        # 设置默认dock布局
        self.setup_default_dock_layout()

        # 强制应用PyQtAds暗色主题
        self.apply_pyqtads_dark_theme()

        
    def create_dock_widgets(self):
        """创建停靠窗口组件"""
        ads = PyQtAds.ads
        
        # 创建各功能面板
        
        # 1. 雷达参数控制面板
        self.control_panel = ControlPanelWidget()
        self.control_dock = ads.CDockWidget("🎛️ 雷达参数控制")
        self.control_dock.setObjectName("ControlDock")
        self.control_dock.setWidget(self.control_panel)
        # 禁用关闭功能，从源头阻止创建关闭按钮
        self.control_dock.setFeature(ads.CDockWidget.DockWidgetClosable, False)

        # 2. 智能对话面板
        self.chat_panel = ChatPanel()
        self.chat_dock = ads.CDockWidget("🤖 智能对话")
        self.chat_dock.setObjectName("ChatDock")
        self.chat_dock.setWidget(self.chat_panel)
        # 禁用关闭功能
        self.chat_dock.setFeature(ads.CDockWidget.DockWidgetClosable, False)


        # 3. 发射信号显示（使用PyQtGraph）
        if FAST_PLOTS_AVAILABLE and is_pyqtgraph_available():
            self.tx_signal_widget = FastSignalPlotWidget("发射信号")
            print("使用PyQtGraph高性能发射信号显示")
        else:
            # 如果PyQtGraph不可用，显示错误信息
            print("[ERROR] PyQtGraph不可用，请安装: pip install pyqtgraph")
            self.tx_signal_widget = FastSignalPlotWidget("发射信号")  # 会显示错误提示
        self.tx_signal_dock = ads.CDockWidget("📡 发射信号")
        self.tx_signal_dock.setObjectName("TxSignalDock")
        self.tx_signal_dock.setWidget(self.tx_signal_widget)
        # 禁用关闭功能
        self.tx_signal_dock.setFeature(ads.CDockWidget.DockWidgetClosable, False)

        # 6. 回波信号显示（使用PyQtGraph）
        if FAST_PLOTS_AVAILABLE and is_pyqtgraph_available():
            self.rx_signal_widget = FastSignalPlotWidget("回波信号")
            print("使用PyQtGraph高性能回波信号显示")
        else:
            print("[ERROR] PyQtGraph不可用，请安装: pip install pyqtgraph")
            self.rx_signal_widget = FastSignalPlotWidget("回波信号")
        self.rx_signal_dock = ads.CDockWidget("📶 回波信号")
        self.rx_signal_dock.setObjectName("RxSignalDock")
        self.rx_signal_dock.setWidget(self.rx_signal_widget)
        # 禁用关闭功能
        self.rx_signal_dock.setFeature(ads.CDockWidget.DockWidgetClosable, False)

        # 6.5. 接收机信号显示（叠加热噪声后的信号）
        if FAST_PLOTS_AVAILABLE and is_pyqtgraph_available():
            self.receiver_signal_widget = FastSignalPlotWidget("接收机信号")
            print("使用PyQtGraph高性能接收机信号显示")
        else:
            print("[ERROR] PyQtGraph不可用，请安装: pip install pyqtgraph")
            self.receiver_signal_widget = FastSignalPlotWidget("接收机信号")
        self.receiver_signal_dock = ads.CDockWidget("📻 接收机信号")
        self.receiver_signal_dock.setObjectName("ReceiverSignalDock")  # 设置唯一的对象名称
        self.receiver_signal_dock.setWidget(self.receiver_signal_widget)
        # 禁用关闭功能
        self.receiver_signal_dock.setFeature(ads.CDockWidget.DockWidgetClosable, False)

        # 7. 脉冲压缩信号显示（使用PyQtGraph）
        if FAST_PLOTS_AVAILABLE and is_pyqtgraph_available():
            self.pc_signal_widget = FastSignalPlotWidget("脉冲压缩信号")
            print("使用PyQtGraph高性能脉冲压缩信号显示")
        else:
            print("[ERROR] PyQtGraph不可用，请安装: pip install pyqtgraph")
            self.pc_signal_widget = FastSignalPlotWidget("脉冲压缩信号")
        self.pc_signal_dock = ads.CDockWidget("🔄 脉冲压缩信号")
        self.pc_signal_dock.setObjectName("PcSignalDock")
        self.pc_signal_dock.setWidget(self.pc_signal_widget)
        # 禁用关闭功能
        self.pc_signal_dock.setFeature(ads.CDockWidget.DockWidgetClosable, False)

        # 8. 距离-多普勒图（使用PyQtGraph高性能组件）
        if FAST_PLOTS_AVAILABLE and is_pyqtgraph_available():
            self.rd_widget = FastRangeDopplerWidget()
            print("使用PyQtGraph高性能距离-多普勒图")
        else:
            print("[ERROR] PyQtGraph不可用，请安装: pip install pyqtgraph")
            self.rd_widget = FastRangeDopplerWidget()  # 会显示错误提示
        self.rd_dock = ads.CDockWidget("🎯 距离-多普勒图")
        self.rd_dock.setObjectName("RdDock")
        self.rd_dock.setWidget(self.rd_widget)
        # 禁用关闭功能
        self.rd_dock.setFeature(ads.CDockWidget.DockWidgetClosable, False)

        # 9. RD图输入矩阵（脉冲压缩矩阵）- 使用与RD图相同的组件
        if FAST_PLOTS_AVAILABLE and is_pyqtgraph_available():
            self.matrix_widget = FastRangeDopplerWidget()
            print("使用PyQtGraph高性能RD图输入矩阵显示")
        else:
            print("[ERROR] PyQtGraph不可用，请安装: pip install pyqtgraph")
            self.matrix_widget = FastRangeDopplerWidget()  # 会显示错误提示
        self.matrix_dock = ads.CDockWidget("📊 RD图输入矩阵")
        self.matrix_dock.setObjectName("MatrixDock")
        self.matrix_dock.setWidget(self.matrix_widget)
        # 禁用关闭功能
        self.matrix_dock.setFeature(ads.CDockWidget.DockWidgetClosable, False)

        # 10. 测量结果显示
        self.measurement_widget = MeasurementDisplayWidget()
        self.measurement_dock = ads.CDockWidget("📋 测量结果")
        self.measurement_dock.setObjectName("MeasurementDock")
        self.measurement_dock.setWidget(self.measurement_widget)
        # 禁用关闭功能
        self.measurement_dock.setFeature(ads.CDockWidget.DockWidgetClosable, False)

    def display_plotting_performance_info(self):
        """显示绘图性能信息"""
        if FAST_PLOTS_AVAILABLE:
            try:
                perf_info = get_performance_info()
                print(f"[OK] {perf_info['message']}")
                if 'performance_note' in perf_info:
                    if perf_info['opengl_enabled']:
                        print(f"[BOOST] {perf_info['performance_note']}")
                    else:
                        print(f"[INFO] {perf_info['performance_note']}")
                if 'expected_speedup' in perf_info:
                    print(f"[PERF] 预期性能提升: {perf_info['expected_speedup']}")
            except:
                print("[OK] PyQtGraph高性能绘图已启用")
        else:
            print("[WARN] 建议安装PyQtGraph以获得10-100倍绘图性能提升: pip install pyqtgraph")
        
    def setup_default_dock_layout(self):
        """设置默认的dock布局"""
        print("设置 PyQtAds 停靠窗口布局...")
        ads = PyQtAds.ads
        
        try:
            # 左侧区域 - 控制和聊天
            area1 = self.dock_manager.addDockWidget(ads.LeftDockWidgetArea, self.control_dock)
            area2 = self.dock_manager.addDockWidget(ads.LeftDockWidgetArea, self.chat_dock)
            
            # 中央区域 - 信号显示
            area3 = self.dock_manager.addDockWidget(ads.CenterDockWidgetArea, self.tx_signal_dock)
            area4 = self.dock_manager.addDockWidget(ads.CenterDockWidgetArea, self.rx_signal_dock)
            area4_5 = self.dock_manager.addDockWidget(ads.CenterDockWidgetArea, self.receiver_signal_dock)
            area5 = self.dock_manager.addDockWidget(ads.CenterDockWidgetArea, self.pc_signal_dock)
            
            # 右侧区域 - 分析结果
            area6 = self.dock_manager.addDockWidget(ads.RightDockWidgetArea, self.rd_dock)
            area7 = self.dock_manager.addDockWidget(ads.RightDockWidgetArea, self.matrix_dock)
            area8 = self.dock_manager.addDockWidget(ads.RightDockWidgetArea, self.measurement_dock)
            
            
            print("PyQtAds 停靠窗口布局设置完成")
            
        except Exception as e:
            print(f"设置布局失败: {e}")
            traceback.print_exc()

    def apply_pyqtads_dark_theme(self):
        """程序化应用PyQtAds暗色主题"""
        try:
            # 获取所有dock widgets并强制设置样式
            dock_widgets = [
                self.control_dock, self.chat_dock, self.tx_signal_dock,
                self.rx_signal_dock, self.receiver_signal_dock, self.pc_signal_dock,
                self.rd_dock, self.matrix_dock, self.measurement_dock
            ]

            # PyQtAds 特定样式
            pyqtads_style = """
                background-color: #161b22;
                color: #f0f6fc;
                border: 2px solid #30363d;
                border-radius: 8px;
            """

            title_bar_style = """
                background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                    stop:0 #21262d, stop:1 #161b22);
                color: #f0f6fc;
                border: 2px solid #30363d;
                border-radius: 6px 6px 0 0;
                font-weight: 600;
                padding: 8px 12px;
            """

            # 强制设置每个dock widget的样式
            for dock in dock_widgets:
                if dock:
                    # 设置dock widget本身的样式
                    dock.setStyleSheet(pyqtads_style)

                    # 尝试获取并设置标题栏样式
                    try:
                        # 查找标题栏组件
                        title_bar = dock.findChild(QWidget, "DockWidgetTitleBar")
                        if title_bar:
                            title_bar.setStyleSheet(title_bar_style)

                        # 查找标签页
                        tab_widget = dock.findChild(QWidget, "DockWidgetTab")
                        if tab_widget:
                            tab_widget.setStyleSheet(title_bar_style)

                        # 查找并设置功能按钮大小
                        def setup_function_buttons(widget):
                            """设置功能按钮大小和样式"""
                            all_buttons = widget.findChildren(QPushButton)
                            for btn in all_buttons:
                                tooltip = btn.toolTip().lower() if btn.toolTip() else ""

                                # 检查是否为功能按钮（需要放大）
                                if any(keyword in tooltip for keyword in ["list all tabs", "detach group", "close group"]):
                                    try:
                                        # 放大功能按钮
                                        btn.setFixedSize(28, 28)
                                        btn.setVisible(True)
                                        btn.setEnabled(True)

                                        # 设置特定颜色
                                        if "list all tabs" in tooltip:
                                            color = "#58a6ff"
                                        elif "detach group" in tooltip:
                                            color = "#fd7e14"
                                        elif "close group" in tooltip:
                                            color = "#f85149"
                                        else:
                                            color = "#f0f6fc"

                                        btn.setStyleSheet(f"""
                                            QPushButton {{
                                                background-color: #21262d;
                                                border: 2px solid #30363d;
                                                border-radius: 5px;
                                                color: {color};
                                                font-size: 16px;
                                                font-weight: bold;
                                                padding: 5px;
                                                margin: 3px;
                                            }}
                                            QPushButton:hover {{
                                                background-color: {color};
                                                border-color: {color};
                                                color: #ffffff;
                                            }}
                                        """)
                                        print(f"设置功能按钮: {btn.toolTip()}")
                                    except Exception as e:
                                        print(f"设置功能按钮失败: {e}")

                        # 对dock本身执行功能按钮设置
                        setup_function_buttons(dock)

                    except Exception as e:
                        print(f"设置dock标题栏样式失败: {e}")

            # 设置dock manager本身的样式
            self.dock_manager.setStyleSheet("""
                QWidget {
                    background-color: #161b22;
                    color: #f0f6fc;
                }
            """)

            print("PyQtAds暗色主题应用完成")

            # 简化的定时器，主要用于维护功能按钮大小
            self.button_maintenance_timer = QTimer()
            self.button_maintenance_timer.timeout.connect(self.maintain_function_buttons)
            self.button_maintenance_timer.start(1000)  # 每秒检查一次即可

        except Exception as e:
            print(f"应用PyQtAds暗色主题失败: {e}")
            traceback.print_exc()

    def maintain_function_buttons(self):
        """维护功能按钮的大小和样式，并增强Tab高亮效果"""
        try:
            # 查找dock manager中的所有按钮
            all_buttons = self.dock_manager.findChildren(QPushButton)
            for btn in all_buttons:
                tooltip = btn.toolTip().lower() if btn.toolTip() else ""

                # 检查是否为功能按钮（确保保持放大状态）
                if any(keyword in tooltip for keyword in ["list all tabs", "detach group", "close group"]):
                    if btn.size().width() < 28 or btn.size().height() < 28:
                        try:
                            btn.setFixedSize(28, 28)
                            btn.setVisible(True)
                            btn.setEnabled(True)
                        except Exception as e:
                            pass

            # 增强激活Tab页的高亮效果
            self.enhance_active_tab_highlight()

        except Exception as e:
            pass  # 忽略定时器执行中的错误

    def enhance_active_tab_highlight(self):
        """增强激活Tab页的高亮效果 - 仅对真正激活的Tab"""
        try:
            # 不使用程序化设置来避免影响所有Tab
            # CSS规则已经足够处理激活状态的高亮
            # 这里只做功能按钮的维护，不干预Tab高亮
            pass
        except Exception as e:
            pass

    def create_menus(self):
        """创建菜单栏"""
        menubar = self.menuBar()
        
        # 文件菜单
        file_menu = menubar.addMenu('文件')
        
        export_action = QAction('导出数据', self)
        export_action.triggered.connect(self.export_data)
        file_menu.addAction(export_action)
        
        file_menu.addSeparator()
        
        save_layout_action = QAction('💾 保存布局', self)
        save_layout_action.triggered.connect(self.save_layout)
        file_menu.addAction(save_layout_action)
        
        restore_layout_action = QAction('📁 恢复布局', self)
        restore_layout_action.triggered.connect(self.restore_layout)
        file_menu.addAction(restore_layout_action)
        
        file_menu.addSeparator()
        
        exit_action = QAction('退出', self)
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)
        
        # 视图菜单
        view_menu = menubar.addMenu('视图')
        
        # 添加dock显示/隐藏控制
        dock_menu = view_menu.addMenu('🪟 面板显示')
        
        # 为每个dock添加显示/隐藏菜单项
        dock_widgets = [
            (self.control_dock, "雷达参数控制"),
            (self.chat_dock, "智能对话"),
            (self.tx_signal_dock, "发射信号"),
            (self.rx_signal_dock, "回波信号"),
            (self.receiver_signal_dock, "接收机信号"),
            (self.pc_signal_dock, "脉冲压缩信号"),
            (self.rd_dock, "距离-多普勒图"),
            (self.matrix_dock, "RD图输入矩阵"),
            (self.measurement_dock, "测量结果")
        ]
        
        for dock, title in dock_widgets:
            action = QAction(title, self)
            action.setCheckable(True)
            action.setChecked(True)
            action.triggered.connect(lambda checked, d=dock: self.toggle_dock_visibility(d, checked))
            dock_menu.addAction(action)
        
        dock_menu.addSeparator()
        
        reset_layout_action = QAction('🔄 重置布局', self)
        reset_layout_action.triggered.connect(self.reset_layout)
        dock_menu.addAction(reset_layout_action)
        
        # 仿真功能菜单（保持原有功能）
        simulation_menu = view_menu.addMenu('🎯 仿真功能')
        
        demo_scenario_action = QAction('🚀 运行演示场景', self)
        demo_scenario_action.triggered.connect(self.run_demo_scenario)
        simulation_menu.addAction(demo_scenario_action)
        
        clear_targets_action = QAction('🗑️ 清空所有目标', self)
        clear_targets_action.triggered.connect(self.clear_all_targets)
        simulation_menu.addAction(clear_targets_action)
        
        # PyQtAds 功能菜单
        pyqtads_menu = view_menu.addMenu('✨ PyQtAds 功能')
        
        demo_docking_action = QAction('🎨 停靠功能演示', self)
        demo_docking_action.triggered.connect(self.demo_pyqtads_features)
        pyqtads_menu.addAction(demo_docking_action)
        
        demo_tabify_action = QAction('📑 标签页功能演示', self)
        demo_tabify_action.triggered.connect(self.demo_tabify_features)
        pyqtads_menu.addAction(demo_tabify_action)
        
        view_menu.addSeparator()
        
        refresh_action = QAction('刷新显示', self)
        refresh_action.triggered.connect(self.refresh_displays)
        view_menu.addAction(refresh_action)
        
        # 帮助菜单
        help_menu = menubar.addMenu('帮助')

        welcome_action = QAction('🎯 欢迎指南', self)
        welcome_action.triggered.connect(self.show_welcome_message)
        help_menu.addAction(welcome_action)

        help_menu.addSeparator()

        about_action = QAction('关于', self)
        about_action.triggered.connect(self.show_about)
        help_menu.addAction(about_action)

        pyqtads_help_action = QAction('📚 PyQtAds 说明', self)
        pyqtads_help_action.triggered.connect(self.show_pyqtads_help)
        help_menu.addAction(pyqtads_help_action)
        
    def toggle_dock_visibility(self, dock, visible):
        """切换dock可见性"""
        if visible:
            dock.show()
        else:
            dock.hide()
            
    def reset_layout(self):
        """重置布局"""
        # 重新设置默认布局
        self.setup_default_dock_layout()
        self.statusBar().showMessage("布局已重置为默认设置")
        
    def save_layout(self):
        """保存布局"""
        try:
            # 使用 PyQtAds 的状态保存功能
            state = self.dock_manager.saveState()
            
            # 保存到文件
            config_file = os.path.join(os.getcwd(), "radar_pyqtads_layout.dat")
            with open(config_file, 'wb') as f:
                f.write(state)
                
            self.statusBar().showMessage(f"布局已保存到: {config_file}")
            
            # 显示确认消息
            QMessageBox.information(self, "布局保存",
                                   f"PyQtAds 停靠布局已保存！\\n\\n保存位置: {config_file}")
            
        except Exception as e:
            self.show_error(f"保存布局失败: {str(e)}")
            
    def restore_layout_on_startup(self):
        """启动时自动恢复布局（静默版本）"""
        try:
            config_file = os.path.join(os.getcwd(), "radar_pyqtads_layout.dat")

            if not os.path.exists(config_file):
                print("没有找到保存的PyQtAds布局文件，使用默认布局")
                return

            # 从文件加载
            with open(config_file, 'rb') as f:
                state = f.read()

            # 恢复 PyQtAds 状态
            self.dock_manager.restoreState(state)

            print("启动时PyQtAds布局自动恢复完成")
            self.statusBar().showMessage("布局已自动恢复", 3000)

        except Exception as e:
            print(f"启动时恢复布局失败: {e}")

    def prewarm_plot_widgets(self):
        """
        预热绘图widgets - 在启动时绘制一次空数据
        这样可以将PyQtGraph/OpenGL/Dock的初始化开销转移到启动阶段
        避免用户第一次看到的仿真绘图有明显延迟
        """
        try:
            print("[性能优化] 预热绘图widgets...")
            import numpy as np
            import time

            perf_start = time.perf_counter()

            # 创建空数据用于预热
            dummy_time = np.linspace(0, 1e-6, 100)
            dummy_signal = np.zeros(100, dtype=complex)

            # 依次绘制所有信号widgets（触发初始化）
            self.tx_signal_widget.plot_signal(dummy_time, dummy_signal, 'complex')
            self.rx_signal_widget.plot_signal(dummy_time, dummy_signal, 'complex')
            self.receiver_signal_widget.plot_signal(dummy_time, dummy_signal, 'complex')
            self.pc_signal_widget.plot_signal(dummy_time, dummy_signal, 'compressed')

            # 清空显示（用户不应该看到这些空数据）
            self.tx_signal_widget.clear_plots()
            self.rx_signal_widget.clear_plots()
            self.receiver_signal_widget.clear_plots()
            self.pc_signal_widget.clear_plots()

            perf_end = time.perf_counter()
            elapsed_ms = (perf_end - perf_start) * 1000

            print(f"[性能优化] 绘图widgets预热完成 ({elapsed_ms:.2f} ms)")
            print(f"[性能优化] 后续绘图将直接进入快速模式")

        except Exception as e:
            print(f"预热绘图widgets失败（不影响正常使用）: {e}")

    def restore_layout(self):
        """恢复布局"""
        try:
            config_file = os.path.join(os.getcwd(), "radar_pyqtads_layout.dat")

            if not os.path.exists(config_file):
                QMessageBox.warning(self, "⚠️ 未找到布局",
                                   "未找到保存的布局文件，请先保存布局。")
                return

            # 从文件加载
            with open(config_file, 'rb') as f:
                state = f.read()

            # 恢复 PyQtAds 状态
            self.dock_manager.restoreState(state)

            self.statusBar().showMessage("布局已恢复")
            QMessageBox.information(self, "布局恢复", "PyQtAds 停靠布局已恢复！")

        except Exception as e:
            self.show_error(f"恢复布局失败: {str(e)}")
            
    def demo_pyqtads_features(self):
        """演示 PyQtAds 功能"""
        demo_msg = QMessageBox(self)
        demo_msg.setWindowTitle("🎨 PyQtAds 停靠功能")
        demo_msg.setIcon(QMessageBox.Information)
        
        demo_text = """🎨 PyQtAds 停靠功能特性：

🚀 专业级停靠系统：
• 🖱️ Visual Studio 风格的停靠指示器
• 📍 精确的停靠位置控制
• 📑 智能标签页自动合并
• ↔️ 流畅的拖拽动画效果

🎯 完整保持功能：
• 🛰️ 完整的雷达仿真功能
• 🤖 智能对话系统
• 📊 实时数据分析

✨ PyQtAds 优势：
• 原生 Qt 实现，性能卓越
• 完整的状态保存和恢复
• 高度可定制的外观
• 专业的用户体验

🎮 操作指南：
1. 拖拽面板标题栏移动面板
2. 观察蓝色停靠指示器出现
3. 拖拽到指示器完成精确停靠
4. 尝试创建标签页组合
5. 使用菜单保存/恢复布局

现在请尝试拖拽任意面板体验 PyQtAds 专业级停靠功能！"""
        
        demo_msg.setText(demo_text)
        demo_msg.exec_()
        
    def demo_tabify_features(self):
        """演示标签页功能"""
        demo_msg = QMessageBox(self)
        demo_msg.setWindowTitle("📑 PyQtAds 智能标签页功能")
        demo_msg.setIcon(QMessageBox.Information)
        
        demo_text = """📑 PyQtAds 智能标签页功能：

🎯 标签页创建：
• 将面板拖拽到另一个面板的中央指示器
• 自动创建专业级标签页容器
• 支持无限数量的面板组合

🔄 标签页操作：
• 点击标签切换面板
• 拖拽标签重新排序
• 拖拽标签到其他位置分离
• 右键标签访问更多选项

✨ 智能管理：
• 自动调整标签栏大小
• 智能处理标签溢出
• 支持嵌套标签页结构
• 保持所有原有功能

🎨 专业外观：
• 高亮显示活动标签
• 平滑的切换动画
• Visual Studio 风格设计
• 响应式布局适配

🔧 高级特性：
• 完整的状态保存
• 布局恢复支持
• 可编程控制接口
• 事件回调机制

试试拖拽各个信号分析面板，体验专业的停靠功能！"""
        
        demo_msg.setText(demo_text)
        demo_msg.exec_()
        
    def show_pyqtads_help(self):
        """显示 PyQtAds 说明"""
        help_msg = QMessageBox(self)
        help_msg.setWindowTitle("📚 PyQtAds 完整功能说明")
        help_msg.setIcon(QMessageBox.Information)
        
        help_text = """📚 PyQtAds 雷达仿真系统完整说明：

🏗️ 技术架构：
• 基于 Qt Advanced Docking System
• 完全保持原有雷达仿真智能体功能
• 使用 PyQtAds Python 绑定
• 提供专业级停靠窗口体验

🎯 完整保持的功能：
1. 🛰️ 雷达仿真引擎
2. 📡 信号处理和显示
3. 🤖 智能对话系统
5. 📊 实时数据分析
6. 🎯 目标检测和跟踪
7. 📈 距离-多普勒图
8. 📋 测量结果显示
9. ⚙️ 参数实时调整

✨ PyQtAds 增强特性：
• Visual Studio 风格停靠指示器
• 专业级拖拽停靠体验
• 智能标签页自动管理
• 完整的状态保存/恢复
• 高性能原生渲染
• 高度可定制化界面

🖱️ 交互操作：
• 拖拽：精确的面板移动和停靠
• 标签：专业的标签页管理
• 指示器：Visual Studio 风格引导
• 菜单：完整的布局控制

🔧 技术实现：
• 基于 PyQtAds 3.8+
• 完全保持原有组件
• 无侵入式集成
• 跨平台完美兼容

这是专业级雷达仿真系统的停靠窗口升级版本！"""
        
        help_msg.setText(help_text)
        help_msg.exec_()
        
    # setHighTechStyle 方法已移除，全局样式在应用程序级别设置
        
    # ==================== 仿真控制功能 ====================
    
    def connect_control_signals(self):
        """连接控制面板信号"""
        self.control_panel.simulation_started.connect(self.start_simulation)
        self.control_panel.simulation_stopped.connect(self.stop_simulation)
        self.control_panel.simulation_paused.connect(self.pause_simulation)  # 新增：暂停
        self.control_panel.simulation_resumed.connect(self.resume_simulation)  # 新增：恢复
        self.control_panel.simulation_reset.connect(self.reset_simulation)
        self.control_panel.target_added.connect(self.add_target)
        self.control_panel.parameter_changed.connect(self.update_radar_parameter)
        self.control_panel.demo_requested.connect(self.run_demo_scenario)
        self.control_panel.clear_targets_requested.connect(self.clear_all_targets)

        # 连接聊天代理的参数更新信号
        self.chat_agent.parameter_updated.connect(self.on_chat_parameter_updated)
        
        # 连接聊天面板信号
        self.chat_panel.command_executed.connect(self.handle_chat_command_threaded)
        
    def setup_timer(self):
        """设置定时器用于从进程读取数据"""
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_displays_from_process)
        # 提高到50Hz刷新频率，最大化界面响应速度
        self.update_interval = 20  # 50Hz（与仿真进程同步）
        
    def setup_worker_connections(self):
        """设置工作线程连接 - 仅用于聊天功能"""
        # 仿真功能已迁移到多进程架构(SimulationProcess)
        # 只保留聊天功能的信号连接
        if self.thread_manager.chat_worker:
            self.thread_manager.chat_worker.message_processed.connect(self.on_chat_message_processed)
            self.thread_manager.chat_worker.processing_error.connect(self.on_chat_error)
            
    def setup_default_scenario(self):
        """设置默认仿真场景"""
        try:
            # 设置优化的雷达参数
            default_params = {
                'frequency': 12.5,
                'power': 1500.0,
                'antenna_gain': 35.0,
                'sampling_rate': 100.0,
                'pulse_width': 10.0,
                'pulse_repetition_time': 1.0,
                'bandwidth': 10.0,
                'receiver_gain_db': 10.0,  # 接收机增益 (LNA Gain)
                'receiver_noise_db': 8.0,  # 接收机噪声系数 (Noise Figure)
                'detection_range': 120.0,
                'noise_factor': 2.5  # 已废弃
            }
            
            self.radar_engine.params.update(default_params)
            self.signal_processor = RadarSignalProcessor(self.radar_engine.params)
            
            # 添加默认目标（单一目标场景）
            # 注意：如果不需要默认目标，可以注释掉这段代码
            default_targets = [
                {'name': '静止目标', 'position': (50, 20, 2), 'velocity': (0, 0, 0), 'rcs': 10.0}  # m/s，静止目标
            ]
            
            for target_info in default_targets:
                self.target_counter += 1
                target = Target(
                    target_info['name'], 
                    target_info['position'], 
                    target_info['velocity'], 
                    target_info['rcs']
                )
                self.radar_engine.add_target(target)
            
            # 同步控制面板参数显示
            self.sync_control_panel_params()

            self.statusBar().showMessage(
                f"已加载默认场景: {len(default_targets)}个目标"
            )

            # 启动时自动恢复保存的布局
            QTimer.singleShot(100, self.restore_layout_on_startup)

            # 预热绘图widgets以避免首次绘制延迟
            QTimer.singleShot(300, self.prewarm_plot_widgets)

            # 启动时自动恢复上次保存的参数
            QTimer.singleShot(500, self.restore_parameters_on_startup)

            # 欢迎信息已移动到帮助菜单中

        except Exception as e:
            self.show_error(f"设置默认场景失败: {str(e)}")

    def setup_default_targets(self):
        """只设置默认目标，不重置雷达参数"""
        try:
            # 添加推荐的默认目标（与界面控件默认值一致）
            # 参考: docs/recommended_scenarios.md
            default_targets = [
                {
                    'name': '慢速移动目标',
                    'position': (50.0, 3.0, 0.0),   # 50 km < 150 km ✓
                    'velocity': (5.0, 2.0, 0.0),    # 5.4 m/s < 7.5 m/s ✓
                    'rcs': 10.0                     # 良好的RCS
                }
            ]

            for target_info in default_targets:
                self.target_counter += 1
                target = Target(
                    target_info['name'],
                    target_info['position'],
                    target_info['velocity'],
                    target_info['rcs']
                )
                self.radar_engine.add_target(target)

            self.statusBar().showMessage(
                f"已添加默认目标: {len(default_targets)}个"
            )

        except Exception as e:
            self.show_error(f"设置默认目标失败: {str(e)}")

    def sync_control_panel_params(self):
        """同步控制面板的参数显示"""
        try:
            self.control_panel.frequency_spin.setValue(self.radar_engine.params['frequency'])
            self.control_panel.power_spin.setValue(self.radar_engine.params['power'])
            self.control_panel.gain_spin.setValue(self.radar_engine.params['antenna_gain'])
            self.control_panel.sampling_rate_spin.setValue(self.radar_engine.params['sampling_rate'])
            self.control_panel.pulse_width_spin.setValue(self.radar_engine.params['pulse_width'])
            self.control_panel.prt_spin.setValue(self.radar_engine.params['pulse_repetition_time'])
            self.control_panel.bandwidth_spin.setValue(self.radar_engine.params['bandwidth'])
            self.control_panel.receiver_gain_spin.setValue(self.radar_engine.params.get('receiver_gain_db', 10.0))
            self.control_panel.receiver_noise_spin.setValue(self.radar_engine.params.get('receiver_noise_db', 8.0))
        except Exception as e:
            print(f"同步参数显示失败: {e}")
            
    def show_welcome_message(self):
        """显示欢迎消息"""
        welcome_msg = QMessageBox(self)
        welcome_msg.setWindowTitle("🎯 雷达仿真智能体 - PyQtAds 版")
        welcome_msg.setIcon(QMessageBox.Information)
        
        welcome_text = """🚀 欢迎使用雷达仿真智能体！

🌟 PyQtAds 专业特性：
• 🎨 Visual Studio 风格停靠指示器
• 📑 智能标签页自动管理
• ↔️ 专业级拖拽停靠体验
• 💾 完整的布局保存/恢复
• ⚡ 原生 Qt 高性能渲染

🎯 完整保持的功能：
• 🛰️ 雷达仿真引擎
• 📡 信号处理和显示
• 🤖 智能对话系统
• 📊 实时数据分析

📊 当前仿真场景：
• 🛩️ 商用客机 (RCS: 15.0 m²)

🎮 PyQtAds 操作：
1. 🖱️ 拖拽面板标题栏移动
2. 📍 观察蓝色停靠指示器
3. 📑 拖拽到中央创建标签页
4. ↔️ 拖拽到边缘创建新区域
5. 💾 使用菜单保存/恢复布局

🚀 快速开始：
• 点击"运行演示场景"启动仿真
• 或体验"停靠功能演示"了解 PyQtAds

现在开始探索 PyQtAds 专业级停靠体验吧！"""
        
        welcome_msg.setText(welcome_text)
        welcome_msg.addButton("🚀 运行演示", QMessageBox.AcceptRole)
        welcome_msg.addButton("🎨 停靠演示", QMessageBox.DestructiveRole)
        welcome_msg.addButton("📖 手动操作", QMessageBox.RejectRole)
        
        choice = welcome_msg.exec_()
        
        if choice == QMessageBox.AcceptRole:
            self.run_demo_scenario()
        elif choice == QMessageBox.DestructiveRole:
            self.demo_pyqtads_features()
        else:
            self.statusBar().showMessage("🎨 体验 PyQtAds：拖拽任意面板标题栏", 8000)
            
    # ==================== 仿真控制方法（完全保持不变） ====================
    
    def start_simulation(self):
        """启动连续仿真"""
        try:
            # 重置进度条跟踪变量
            self._last_progress = -1  # 设置为-1确保第一次更新时会触发

            # 获取设置的仿真时长
            simulation_duration = self.control_panel.get_simulation_duration()  # 秒
            self.simulation_target_duration = simulation_duration

            # 使用仿真进程启动仿真（多进程架构，完全避免GIL竞争）
            self.sim_process.start(duration=simulation_duration)

            # 启动界面更新定时器
            if not self.update_timer.isActive():
                self.update_timer.start(self.update_interval)

            # 更新UI状态
            self.control_panel.set_simulation_running(True)

            self.statusBar().showMessage(f"仿真运行中... (时长: {simulation_duration}秒)")
            self.compact_status_bar.update_status("仿真运行中", 0)
        except Exception as e:
            self.show_error(f"启动仿真失败: {str(e)}")

    def stop_simulation(self):
        """停止仿真"""
        try:
            # 停止仿真进程
            self.sim_process.stop()

            # 停止界面更新定时器
            self.update_timer.stop()

            # 更新UI状态
            self.control_panel.set_simulation_running(False)

            self.statusBar().showMessage("仿真已停止")
            self.compact_status_bar.update_status("仿真已停止", None)
            self.compact_status_bar.hide_simulation_time()  # 隐藏仿真时间显示
        except Exception as e:
            self.show_error(f"停止仿真失败: {str(e)}")

    def pause_simulation(self):
        """暂停仿真"""
        try:
            self.sim_process.pause()
            self.statusBar().showMessage("仿真已暂停")
            self.compact_status_bar.update_status("仿真已暂停", None)
            print("[GUI] 仿真已暂停")
        except Exception as e:
            self.show_error(f"暂停仿真失败: {str(e)}")

    def resume_simulation(self):
        """恢复仿真"""
        try:
            self.sim_process.resume()
            self.statusBar().showMessage("仿真已恢复")
            self.compact_status_bar.update_status("仿真运行中", None)
            print("[GUI] 仿真已恢复")
        except Exception as e:
            self.show_error(f"恢复仿真失败: {str(e)}")
            
    def reset_simulation(self):
        """重置仿真"""
        try:
            self.radar_engine.reset_simulation()

            # 停止仿真进程
            self.sim_process.stop()

            # 重置进度条跟踪变量
            if hasattr(self, '_last_progress'):
                del self._last_progress

            # simulation_target_duration 保留，可能用于重新开始仿真

            # 停止界面更新定时器
            self.update_timer.stop()

            self.statusBar().showMessage("仿真已重置")
            self.compact_status_bar.update_status("仿真已重置", None)
            self.compact_status_bar.hide_simulation_time()  # 隐藏仿真时间显示
            self.clear_displays()
        except Exception as e:
            self.show_error(f"重置仿真失败: {str(e)}")

    def _on_chat_simulation_started(self):
        """聊天触发的仿真启动回调"""
        # 初始化仿真目标时长（聊天启动时为无限运行）
        self.simulation_target_duration = None

        # 启动界面更新定时器
        if not self.update_timer.isActive():
            self.update_timer.start(self.update_interval)

        # 更新UI状态
        self.control_panel.set_simulation_running(True)
        self.statusBar().showMessage("仿真运行中... (聊天启动)")
        self.compact_status_bar.update_status("仿真运行中", None)  # 无限运行，不显示进度条

    def _on_chat_simulation_stopped(self):
        """聊天触发的仿真停止回调"""
        # 停止界面更新定时器
        self.update_timer.stop()

        # 更新UI状态
        self.control_panel.set_simulation_running(False)
        self.statusBar().showMessage("仿真已停止 (聊天停止)")
        self.compact_status_bar.update_status("仿真已停止", None)
        self.compact_status_bar.hide_simulation_time()

    def add_target(self, target_data):
        """添加目标"""
        try:
            self.target_counter += 1
            target_id = f"目标{self.target_counter}"
            
            position = (target_data['x'], target_data['y'], target_data['z'])
            velocity = (target_data['vx'], target_data['vy'], target_data['vz'])
            rcs = target_data['rcs']
            
            target = Target(target_id, position, velocity, rcs)
            self.radar_engine.add_target(target)
            
            self.statusBar().showMessage(f"已添加{target_id}，当前目标数: {len(self.radar_engine.targets)}")
            self.compact_status_bar.update_status(f"已添加{target_id}", None)
            # 目标数据会在下一次定时器更新时自动显示，无需手动触发
        except Exception as e:
            self.show_error(f"添加目标失败: {str(e)}")
            
    def update_radar_parameter(self, param_name, value):
        """更新雷达参数"""
        try:
            self.radar_engine.params[param_name] = value
            self.signal_processor = RadarSignalProcessor(self.radar_engine.params)

            self.statusBar().showMessage(f"雷达参数 {param_name} 已更新为 {value}")
            self.compact_status_bar.update_status(f"参数已更新: {param_name}", None)
        except Exception as e:
            self.show_error(f"更新参数失败: {str(e)}")

    def on_chat_parameter_updated(self, param_name: str, value: float):
        """处理聊天代理的参数更新信号"""
        try:
            # 1. 更新雷达引擎参数
            self.radar_engine.params[param_name] = value
            self.signal_processor = RadarSignalProcessor(self.radar_engine.params)

            # 2. 更新GUI控件
            self.control_panel.update_radar_parameter(param_name, value)

            # 3. 更新状态栏
            self.statusBar().showMessage(f"AI设置: {param_name} = {value}")
            self.compact_status_bar.update_status(f"AI参数更新: {param_name}", None)

            print(f"SUCCESS: 聊天代理参数更新完成 - {param_name}: {value}")
        except Exception as e:
            print(f"ERROR: 处理参数更新失败: {e}")
            self.show_error(f"参数同步失败: {str(e)}")
            
    def run_demo_scenario(self):
        """添加默认目标"""
        try:
            self.radar_engine.targets.clear()
            self.target_counter = 0
            self.setup_default_targets()  # 只设置默认目标，不重置雷达参数
            self.statusBar().showMessage("已添加默认目标，请手动启动仿真")
        except Exception as e:
            self.show_error(f"添加默认目标失败: {str(e)}")
            
    def clear_all_targets(self):
        """清空所有目标"""
        try:
            self.radar_engine.targets.clear()
            self.target_counter = 0
            self.clear_displays()
            self.statusBar().showMessage("已清空所有目标")
        except Exception as e:
            self.show_error(f"清空目标失败: {str(e)}")
            
    # ==================== 显示更新方法 ====================

    def clear_displays(self):
        """清空所有显示"""
        for widget in [self.tx_signal_widget, self.rx_signal_widget, self.receiver_signal_widget, self.pc_signal_widget]:
            try:
                # PyQtGraph组件清空
                if hasattr(widget, 'clear_plots'):
                    widget.clear_plots()
                elif hasattr(widget, 'time_plot') and hasattr(widget, 'freq_plot'):
                    # 备用清空方法
                    widget.time_plot.clear()
                    widget.freq_plot.clear()
            except Exception as e:
                print(f"清空信号显示组件失败: {e}")

        # 清空RD图（PyQtGraph组件）
        try:
            if hasattr(self.rd_widget, 'clear_plots'):
                self.rd_widget.clear_plots()
            elif hasattr(self.rd_widget, 'image_view'):
                self.rd_widget.image_view.clear()
        except Exception as e:
            print(f"清空RD图组件失败: {e}")

        # 清空脉冲压缩矩阵图（PyQtGraph组件）
        try:
            if hasattr(self.matrix_widget, 'clear_plots'):
                self.matrix_widget.clear_plots()
            elif hasattr(self.matrix_widget, 'image_view'):
                self.matrix_widget.image_view.clear()
        except Exception as e:
            print(f"清空矩阵图组件失败: {e}")

        # 清空测量结果表格
        try:
            self.measurement_widget.table.setRowCount(0)
            self.measurement_widget.stats_label.setText("统计信息: 检测目标数: 0")
        except Exception as e:
            print(f"清空测量结果表格失败: {e}")
        
    def refresh_displays(self):
        """刷新显示 - 定时器会自动更新，无需手动触发"""
        pass
        
    def export_data(self):
        """导出数据"""
        try:
            data = self.radar_engine.export_detection_data()
            filename, _ = QFileDialog.getSaveFileName(
                self, '导出仿真数据', 
                f'radar_data_{int(self.radar_engine.simulation_time)}.json',
                'JSON文件 (*.json)'
            )
            if filename:
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write(data)
                QMessageBox.information(self, '导出成功', f'数据已导出到: {filename}')
        except Exception as e:
            self.show_error(f"导出数据失败: {str(e)}")
            
    # ==================== 聊天和语音处理（完全保持不变） ====================
    
    def handle_chat_command_threaded(self, command):
        """线程化聊天命令处理"""
        try:
            if self.thread_manager.chat_worker:
                self.thread_manager.chat_worker.process_message(command)
            else:
                response = self.chat_agent.process_message(command)
                self.chat_panel.add_assistant_response(response)
        except Exception as e:
            error_msg = f"处理聊天命令失败: {str(e)}"
            self.chat_panel.add_error_message(error_msg)
            
            
    # ==================== 回调方法（完全保持不变） ====================
    
    def on_thread_status_updated(self, thread_type, status):
        """线程状态更新回调"""
        # 系统状态窗口已删除
        pass

    def on_progress_updated(self, operation, progress):
        """进度更新回调"""
        # 系统状态窗口已删除
        self.compact_status_bar.update_status(operation, progress)

    def _prepare_target_data_for_display(self):
        """准备用于显示的目标数据（字典格式）"""
        try:
            if not self.radar_engine.targets:
                return []

            current_targets = []
            radar_position = getattr(self.radar_engine, 'radar_position', np.array([0, 0, 0]))

            for target in self.radar_engine.targets.values():
                # 计算当前目标相对雷达的参数
                range_val, azimuth, elevation = target.get_range_azimuth_elevation(radar_position)

                # 计算径向速度
                position_vector = target.position - radar_position
                velocity_vector = target.velocity / 3.6  # 转换为m/s
                if np.linalg.norm(position_vector) > 0:
                    radial_unit = position_vector / np.linalg.norm(position_vector)
                    radial_velocity = np.dot(velocity_vector, radial_unit)
                else:
                    radial_velocity = 0

                current_targets.append({
                    'id': target.id,
                    'range': range_val,
                    'azimuth': azimuth,
                    'elevation': elevation,
                    'radial_velocity': radial_velocity,
                    'rcs': target.rcs,
                    'position': target.position.copy(),
                    'velocity': target.velocity.copy()
                })

            return current_targets
        except Exception as e:
            print(f"准备目标数据失败: {e}")
            return []

    # ===== 以下回调函数已废弃（对应的worker已迁移到多进程架构） =====
    # 保留函数定义以防止引用错误，但不再使用

    def on_simulation_started(self):
        """仿真开始回调 - 已废弃"""
        pass

    def on_simulation_finished(self):
        """仿真完成回调 - 已废弃"""
        pass

    def on_continuous_simulation_started(self):
        """连续仿真开始回调 - 已废弃"""
        pass

    def on_continuous_simulation_finished(self):
        """连续仿真完成回调 - 已废弃"""
        pass

    def on_continuous_simulation_error(self, error_msg):
        """连续仿真错误回调 - 已废弃"""
        pass

    def update_displays_from_process(self):
        """
        从仿真进程读取数据并更新界面（非阻塞）

        关键优势：
        - 这个函数在主进程中运行，有独立的GIL
        - 仿真进程也有独立的GIL
        - 两个进程真正并行，互不阻塞
        """
        try:
            import time
            t_start = time.perf_counter()

            # ===== 核心：非阻塞读取 =====
            result = self.sim_process.get_latest_result()

            if not result:
                # 没有新数据，直接返回（不阻塞）
                return

            # 检查错误
            if 'error' in result:
                self.show_error(f"仿真错误: {result['error']}")
                self.stop_simulation()
                return

            # 更新状态栏
            sim_time = result.get('simulation_time', 0.0)
            self.compact_status_bar.update_simulation_time(sim_time)

            # 计算进度
            if hasattr(self, 'simulation_target_duration') and self.simulation_target_duration is not None and self.simulation_target_duration > 0:
                progress = min(int((sim_time / self.simulation_target_duration) * 100), 100)
                status_msg = f"仿真中 (总时长: {self.simulation_target_duration:.1f}s)"
            else:
                progress = None  # 无限运行模式，不显示进度条
                status_msg = "仿真运行中"

            self.compact_status_bar.update_status(status_msg, progress)

            # 更新雷达模式
            radar_mode = result.get('radar_mode', 'search')
            self.compact_status_bar.update_radar_mode(radar_mode)

            # ===== 智能更新信号显示（降低频率） =====
            signal_data = result.get('signal_data', {})
            if signal_data:
                # 限制信号更新频率为2Hz
                if not hasattr(self, '_last_signal_update_time'):
                    self._last_signal_update_time = 0

                current_time = time.time()
                if current_time - self._last_signal_update_time >= 0.5:
                    self._last_signal_update_time = current_time
                    self._update_signal_plots(signal_data)

            # 更新测量结果
            measurements = result.get('measurements', [])
            if measurements:
                targets_dict = self._prepare_target_data_for_display()
                self.measurement_widget.update_measurements(measurements, targets_dict)

            t_end = time.perf_counter()
            update_time = (t_end - t_start) * 1000

            # 性能监控：计算仿真速度倍率
            if not hasattr(self, '_last_perf_print'):
                self._last_perf_print = 0
                self._last_sim_time = 0
                self._last_real_time = time.time()

            if time.time() - self._last_perf_print >= 1.0:
                # 计算仿真速度倍率 = 仿真时间增量 / 真实时间增量
                real_time_delta = time.time() - self._last_real_time
                sim_time_delta = sim_time - self._last_sim_time
                speed_ratio = sim_time_delta / real_time_delta if real_time_delta > 0 else 0

                self._last_perf_print = time.time()
                self._last_sim_time = sim_time
                self._last_real_time = time.time()

        except Exception as e:
            print(f"界面更新失败: {e}")
            import traceback
            traceback.print_exc()

    def _update_signal_plots(self, signal_data):
        """更新信号图（从signal_data中提取并绘制）"""
        try:
            # 获取信号处理器
            signal_processor = self.get_signal_processor()

            # 提取信号数据
            tx_time = signal_data.get('tx_time', np.array([]))
            rx_time = signal_data.get('rx_time', np.array([]))
            tx_signal = signal_data.get('tx_signal', np.array([]))
            rx_signal = signal_data.get('rx_signal', np.array([]))
            receiver_signal = signal_data.get('receiver_signal', np.array([]))  # 接收机信号（叠加热噪声后）
            compressed_signal = signal_data.get('compressed_signal', np.array([]))

            # 关键：使用相对时间避免浮点精度累积误差
            # 长时间运行后，大数(60s) + 小数(10ns) 会导致精度损失，信号出现锯齿
            # 解决方案：转换为相对时间（从各自起始时间计算）
            # 注意：虽然叫"相对时间"，但仍然保持从仿真开始的语义（只是避免了浮点精度问题）
            tx_time_rel = tx_time - tx_time[0] if len(tx_time) > 0 else tx_time
            rx_time_rel = rx_time - rx_time[0] if len(rx_time) > 0 else rx_time

            if compressed_signal is not None and len(compressed_signal) > 0:
                # 脉冲压缩信号长度 = len(tx) + len(rx) - 1
                # 生成对应的时间轴
                pc_start_time = rx_time[0] if len(rx_time) > 0 else 0
                pc_duration = len(compressed_signal) / signal_processor.fs
                pc_time = pc_start_time + np.arange(len(compressed_signal)) / signal_processor.fs
                pc_time_rel = pc_time - pc_time[0]
            else:
                pc_time_rel = tx_time_rel
                compressed_signal = np.zeros_like(tx_signal)

            # 绘制信号（使用相对时间避免锯齿，X轴范围从0开始但代表绝对时间的相对表示）
            self.tx_signal_widget.plot_signal(tx_time_rel, tx_signal, 'complex')
            self.rx_signal_widget.plot_signal(rx_time_rel, rx_signal, 'complex')
            # 绘制接收机信号（叠加热噪声后的信号）
            if receiver_signal is not None and len(receiver_signal) > 0:
                self.receiver_signal_widget.plot_signal(rx_time_rel, receiver_signal, 'complex')
            self.pc_signal_widget.plot_signal(pc_time_rel, compressed_signal, 'compressed')

            # 更新RD图和RD图输入矩阵（如果相参积累完成）
            if signal_data.get('coherent_integration_complete', False):
                # 提取RD图数据
                rd_map = signal_data.get('rd_map')
                range_axis = signal_data.get('range_axis')
                doppler_axis = signal_data.get('doppler_axis')
                pulse_compression_matrix = signal_data.get('pulse_compression_matrix')

                # 绘制RD图
                if rd_map is not None and range_axis is not None and doppler_axis is not None:
                    self.rd_widget.plot_rd_map(range_axis, doppler_axis, rd_map)

                # 绘制RD图输入矩阵（脉冲压缩矩阵）
                if pulse_compression_matrix is not None:
                    self.matrix_widget.plot_matrix(
                        pulse_compression_matrix,
                        row_label="脉冲索引",
                        col_label="距离bin"
                    )

        except Exception as e:
            print(f"信号绘图失败: {e}")

    # update_simple_target_display已废弃并删除 - 功能已内联到update_displays_from_shared_data
    # _should_update_display已废弃并删除 - 逻辑已内联到update_displays_from_shared_data

    def _should_update_signals(self, step: int, total_steps: int) -> bool:
        """智能判断是否应该更新信号显示"""
        # 总是更新第1步和最后一步
        if step == 1 or step == total_steps:
            return True

        # 根据总步数调整更新频率
        if total_steps <= 10:
            # 少于10步：每步都更新
            return True
        elif total_steps <= 50:
            # 10-50步：每2步更新一次
            return step % 2 == 0
        elif total_steps <= 100:
            # 50-100步：每5步更新一次
            return step % 5 == 0
        else:
            # 超过100步：每10步更新一次
            return step % 10 == 0

    # update_displays_with_signal_data已废弃并删除 - 功能已内联到update_displays_from_shared_data

    def on_simulation_error(self, error_msg):
        """仿真错误回调 - 已废弃"""
        pass

    # on_signals_generated已废弃并删除 - 功能已内联到update_displays_from_shared_data

    # on_measurements_updated已废弃并删除 - 功能已内联到update_displays_from_shared_data
            
    def on_processing_error(self, error_msg):
        """信号处理错误回调"""
        self.show_error(f"信号处理错误: {error_msg}")
        self.compact_status_bar.set_error_status(error_msg)
        
    def on_chat_message_processed(self, response):
        """聊天消息处理完成回调"""
        try:
            self.chat_panel.add_assistant_response(response)
            # 数据更新会在下一次定时器触发时自动显示
        except Exception as e:
            self.show_error(f"处理聊天回复失败: {str(e)}")
            
    def on_chat_error(self, error_msg):
        """聊天处理错误回调"""
        self.chat_panel.add_error_message(f"消息处理错误: {error_msg}")
        self.compact_status_bar.set_error_status(error_msg)
        
    # ==================== 辅助方法（完全保持不变） ====================
    
    def show_about(self):
        """显示关于信息"""
        about_msg = QMessageBox(self)
        about_msg.setWindowTitle("🎯 关于雷达仿真智能体")
        about_msg.setIcon(QMessageBox.Information)
        
        about_text = '''🎯 雷达仿真智能体系统 v3.0 - PyQtAds 版
            
🚀 基于 PyQtAds 停靠窗口技术
⚡ 完全保持雷达仿真智能体功能
🌌 深蓝色科幻界面设计
            
✨ 完整保持的核心功能:
• 📡 发射信号生成和显示
• 📶 回波信号仿真
• 🔄 脉冲压缩处理
• 🎯 距离-多普勒图生成
• 📊 目标检测和测量
• 🤖 智能对话交互
• 🎤 语音控制支持

🎨 PyQtAds 专业特色:
• Visual Studio 风格停靠指示器
• 专业级拖拽停靠体验
• 智能标签页自动管理
• 完整的状态保存/恢复
• 原生 Qt 高性能渲染
            
💻 技术支持: AI开发团队
🌟 版本: PyQtAds 专业版'''
        
        about_msg.setText(about_text)
        about_msg.exec_()
            
    def show_error(self, message):
        """显示错误信息"""
        error_msg = QMessageBox(self)
        error_msg.setWindowTitle("⚠️ 系统错误")
        error_msg.setIcon(QMessageBox.Critical)
        error_msg.setText(f"⚠️ 系统错误:\n\n{message}")
        error_msg.exec_()

    def save_parameters(self):
        """保存当前所有参数到配置文件"""
        try:
            # 1. 获取雷达参数
            radar_params = self.control_panel.get_radar_parameters()

            # 2. 获取目标参数
            targets = []
            for target_id, target in self.radar_engine.targets.items():
                target_data = {
                    'id': target_id,
                    'position': list(target.position),  # numpy数组转列表
                    'velocity': list(target.velocity),
                    'rcs': float(target.rcs)
                }
                targets.append(target_data)

            # 3. 获取仿真参数
            simulation_params = {
                'duration': self.control_panel.get_simulation_duration()
            }

            # 4. 保存到文件
            success = self.config_manager.save_config(radar_params, targets, simulation_params)

            if success:
                print("[参数保存] 所有参数已保存")
            else:
                print("[参数保存] 保存失败")

        except Exception as e:
            print(f"[参数保存] 保存参数时出错: {e}")

    def restore_parameters_on_startup(self):
        """启动时恢复上次保存的参数（静默版本）"""
        try:
            if not self.config_manager.config_exists():
                print("[参数恢复] 没有找到保存的配置文件")
                return

            # 加载配置
            config = self.config_manager.load_config()
            if not config:
                return

            # 1. 恢复雷达参数
            radar_params = config.get('radar_params', {})
            if radar_params:
                # 更新雷达引擎参数
                self.radar_engine.params.update(radar_params)
                # 同步到控制面板
                for param_name, value in radar_params.items():
                    self.control_panel.update_radar_parameter(param_name, value)
                print(f"[参数恢复] 已恢复雷达参数: {len(radar_params)}个")

            # 2. 恢复目标
            targets_data = config.get('targets', [])
            if targets_data:
                # 清空现有目标
                self.radar_engine.targets.clear()
                self.target_counter = 0

                # 添加保存的目标
                for target_data in targets_data:
                    self.target_counter += 1
                    target = Target(
                        target_data['id'],
                        tuple(target_data['position']),
                        tuple(target_data['velocity']),
                        target_data['rcs']
                    )
                    self.radar_engine.add_target(target)

                print(f"[参数恢复] 已恢复目标: {len(targets_data)}个")

            # 3. 恢复仿真参数
            simulation_params = config.get('simulation_params', {})
            if simulation_params:
                duration = simulation_params.get('duration')
                if duration:
                    self.control_panel.set_simulation_duration(duration)
                print(f"[参数恢复] 已恢复仿真参数")

            self.statusBar().showMessage(
                f"参数已恢复: {len(radar_params)}个雷达参数, {len(targets_data)}个目标",
                3000
            )

        except Exception as e:
            print(f"[参数恢复] 恢复参数时出错: {e}")
            import traceback
            traceback.print_exc()

    def closeEvent(self, event):
        """关闭事件"""
        try:
            reply = QMessageBox.question(self, '确认退出',
                                       '确定要退出雷达仿真系统吗？',
                                       QMessageBox.Yes | QMessageBox.No,
                                       QMessageBox.No)

            if reply == QMessageBox.Yes:
                # 静默保存布局（不显示提示）
                try:
                    state = self.dock_manager.saveState()
                    config_file = os.path.join(os.getcwd(), "radar_pyqtads_layout.dat")
                    with open(config_file, 'wb') as f:
                        f.write(state)
                except:
                    pass  # 忽略保存失败

                # 保存参数（不显示提示）
                try:
                    self.save_parameters()
                except Exception as e:
                    print(f"保存参数失败: {e}")

                # 停止定时器和进程
                if hasattr(self, 'update_timer'):
                    self.update_timer.stop()
                if hasattr(self, 'sim_process'):
                    self.sim_process.stop()
                # 保留thread_manager用于聊天功能
                if hasattr(self, 'thread_manager'):
                    self.thread_manager.stop_all_workers()
                if hasattr(self, 'button_maintenance_timer'):
                    self.button_maintenance_timer.stop()

                event.accept()
            else:
                event.ignore()
                
        except Exception as e:
            print(f"关闭程序时发生错误: {e}")
            event.accept()

def apply_global_dark_theme(app):
    """应用全局黑蓝色主题到整个应用程序"""
    global_dark_theme = """
        /* ============= 主窗口和对话框基础样式 ============= */
        QMainWindow, QDialog, QMessageBox, QWidget {
            background-color: #0d1117;
            color: #58a6ff;
            font-family: 'Segoe UI', 'Microsoft YaHei', 'Arial', sans-serif;
            font-size: 12px;
        }

        /* ============= 菜单栏样式 ============= */
        QMenuBar {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #161b22, stop:1 #0d1117);
            border-bottom: 2px solid #1f6feb;
            color: #f0f6fc;
            padding: 6px;
            font-weight: 600;
            spacing: 3px;
        }

        QMenuBar::item {
            background-color: transparent;
            padding: 8px 16px;
            border-radius: 6px;
            margin: 2px;
        }

        QMenuBar::item:selected {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #1f6feb, stop:1 #0969da);
            border: 1px solid #388bfd;
            color: #ffffff;
        }

        QMenuBar::item:pressed {
            background-color: #0969da;
        }

        /* ============= 下拉菜单样式 ============= */
        QMenu {
            background-color: #161b22;
            border: 2px solid #30363d;
            border-radius: 8px;
            color: #f0f6fc;
            padding: 6px;
            margin: 2px;
        }

        QMenu::item {
            background-color: transparent;
            padding: 10px 24px;
            border-radius: 6px;
            margin: 2px;
            min-width: 120px;
        }

        QMenu::item:selected {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #1f6feb, stop:1 #0969da);
            color: #ffffff;
        }

        QMenu::separator {
            height: 1px;
            background-color: #30363d;
            margin: 5px 10px;
        }

        /* ============= 状态栏样式 ============= */
        QStatusBar {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #161b22, stop:1 #0d1117);
            border-top: 2px solid #1f6feb;
            color: #58a6ff;
            font-weight: 600;
            padding: 6px;
        }

        /* ============= 按钮样式 ============= */
        QPushButton {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #21262d, stop:0.5 #161b22, stop:1 #0d1117);
            border: 2px solid #30363d;
            border-radius: 8px;
            color: #f0f6fc;
            font-weight: 600;
            padding: 10px 18px;
            margin: 3px;
            min-height: 16px;
            min-width: 60px;
        }

        QPushButton:hover {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #1f6feb, stop:0.5 #0969da, stop:1 #0550ae);
            border: 2px solid #388bfd;
            color: #ffffff;
            /* box-shadow removed - not supported in PyQt5 */
        }

        QPushButton:pressed {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #0550ae, stop:0.5 #033d8b, stop:1 #0a3069);
            border: 2px solid #1f6feb;
            color: #ffffff;
        }

        QPushButton:disabled {
            background-color: #161b22;
            border: 2px solid #21262d;
            color: #6e7681;
        }

        /* ============= 标签样式 ============= */
        QLabel {
            color: #f0f6fc;
            background-color: transparent;
            font-weight: 500;
            padding: 2px;
        }

        /* ============= 输入框样式 ============= */
        QLineEdit, QTextEdit, QPlainTextEdit {
            background-color: #0d1117;
            border: 2px solid #30363d;
            border-radius: 8px;
            color: #f0f6fc;
            padding: 10px;
            font-family: 'Consolas', 'Courier New', monospace;
            font-size: 11px;
            selection-background-color: #1f6feb;
            selection-color: #ffffff;
        }

        QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {
            border: 2px solid #1f6feb;
            background-color: #161b22;
            /* box-shadow removed - not supported in PyQt5 */
        }

        QLineEdit:hover, QTextEdit:hover, QPlainTextEdit:hover {
            border: 2px solid #58a6ff;
        }

        /* ============= 数字输入框样式 ============= */
        QSpinBox, QDoubleSpinBox {
            background-color: #0d1117;
            border: 2px solid #30363d;
            border-radius: 8px;
            color: #f0f6fc;
            padding: 8px;
            font-weight: 500;
            selection-background-color: #1f6feb;
        }

        QSpinBox:focus, QDoubleSpinBox:focus {
            border: 2px solid #1f6feb;
            background-color: #161b22;
            /* box-shadow removed - not supported in PyQt5 */
        }

        QSpinBox:hover, QDoubleSpinBox:hover {
            border: 2px solid #58a6ff;
        }

        QSpinBox::up-button, QDoubleSpinBox::up-button,
        QSpinBox::down-button, QDoubleSpinBox::down-button {
            background-color: #21262d;
            border: 1px solid #30363d;
            border-radius: 4px;
            width: 16px;
            height: 12px;
        }

        QSpinBox::up-button:hover, QDoubleSpinBox::up-button:hover,
        QSpinBox::down-button:hover, QDoubleSpinBox::down-button:hover {
            background-color: #1f6feb;
        }

        /* ============= 组合框样式 ============= */
        QGroupBox {
            background-color: #161b22;
            border: 2px solid #30363d;
            border-radius: 10px;
            color: #f0f6fc;
            font-weight: 600;
            font-size: 15px;
            margin: 12px;
            padding-top: 22px;
        }

        QGroupBox::title {
            subcontrol-origin: margin;
            subcontrol-position: top left;
            left: 15px;
            top: -10px;
            padding: 0 12px;
            background-color: #1f6feb;
            color: #ffffff;
            border-radius: 6px;
            font-size: 15px;
            margin-top: -8px;
        }

        /* ============= 表格样式 ============= */
        QTableWidget {
            background-color: #0d1117;
            border: 2px solid #30363d;
            border-radius: 8px;
            color: #f0f6fc;
            selection-background-color: #1f6feb;
            selection-color: #ffffff;
            gridline-color: #21262d;
            font-size: 11px;
        }

        QTableWidget::item {
            padding: 8px;
            border-bottom: 1px solid #21262d;
        }

        QTableWidget::item:hover {
            background-color: #21262d;
        }

        QTableWidget::item:selected {
            background-color: #1f6feb;
            color: #ffffff;
        }

        QHeaderView::section {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #21262d, stop:1 #161b22);
            border: 1px solid #30363d;
            color: #58a6ff;
            font-weight: 600;
            padding: 8px;
        }

        /* ============= 滚动条样式 ============= */
        QScrollBar:vertical {
            background-color: #161b22;
            width: 14px;
            border-radius: 7px;
            margin: 0;
        }

        QScrollBar::handle:vertical {
            background-color: #30363d;
            border-radius: 7px;
            min-height: 20px;
            margin: 2px;
        }

        QScrollBar::handle:vertical:hover {
            background-color: #58a6ff;
        }

        QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
            height: 0;
        }

        QScrollBar:horizontal {
            background-color: #161b22;
            height: 14px;
            border-radius: 7px;
            margin: 0;
        }

        QScrollBar::handle:horizontal {
            background-color: #30363d;
            border-radius: 7px;
            min-width: 20px;
            margin: 2px;
        }

        QScrollBar::handle:horizontal:hover {
            background-color: #58a6ff;
        }

        QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
            width: 0;
        }

        /* ============= 进度条样式 ============= */
        QProgressBar {
            background-color: #161b22;
            border: 2px solid #30363d;
            border-radius: 8px;
            color: #f0f6fc;
            text-align: center;
            font-weight: 600;
            height: 20px;
        }

        QProgressBar::chunk {
            background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
                stop:0 #1f6feb, stop:1 #58a6ff);
            border-radius: 6px;
            margin: 2px;
        }

        /* ============= 选项卡样式 ============= */
        QTabWidget::pane {
            background-color: #161b22;
            border: 2px solid #30363d;
            border-radius: 8px;
        }

        QTabBar::tab {
            background-color: #21262d;
            border: 2px solid #30363d;
            border-bottom: none;
            border-radius: 8px 8px 0 0;
            color: #f0f6fc;
            padding: 10px 20px;
            margin-right: 2px;
            font-weight: 500;
        }

        QTabBar::tab:selected {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #1f6feb, stop:1 #0969da);
            color: #ffffff;
            font-weight: 600;
        }

        QTabBar::tab:hover:!selected {
            background-color: #30363d;
            border-color: #58a6ff;
        }

        /* ============= 对话框专用样式 ============= */
        QMessageBox {
            background-color: #161b22;
            border: 2px solid #30363d;
            border-radius: 12px;
            color: #f0f6fc;
        }

        QMessageBox QLabel {
            color: #f0f6fc;
            font-size: 13px;
            padding: 10px;
        }

        QMessageBox QPushButton {
            min-width: 80px;
            padding: 8px 20px;
            margin: 5px;
        }

        QDialog {
            background-color: #161b22;
            border: 2px solid #30363d;
            border-radius: 12px;
        }

        /* ============= 工具提示样式 ============= */
        QToolTip {
            background-color: #21262d;
            border: 2px solid #58a6ff;
            border-radius: 6px;
            color: #f0f6fc;
            padding: 8px;
            font-size: 11px;
            opacity: 220;
        }

        /* ============= PyQtAds 停靠窗口专用样式 ============= */
        /* 停靠窗口容器 */
        ads--CDockContainerWidget {
            background-color: #161b22;
            border: 2px solid #30363d;
            border-radius: 10px;
        }

        /* 所有Tab页的基础样式 - 非激活状态 */
        ads--CDockWidgetTab {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #21262d, stop:1 #161b22);
            border: 2px solid #30363d;
            border-bottom: none;
            border-radius: 8px 8px 0 0;
            color: #f0f6fc;
            padding: 10px 15px;
            margin-right: 2px;
            font-weight: 600;
            font-size: 12px;
            min-height: 20px;
        }

        /* 激活的Tab页 - 蓝色边框高亮 */
        ads--CDockWidgetTab:selected {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #21262d, stop:1 #161b22) !important;
            color: #ffffff !important;
            border-top: 3px solid #1f6feb !important;
            border-left: 3px solid #1f6feb !important;
            border-right: 3px solid #1f6feb !important;
            border-bottom: none !important;
            border-radius: 8px 8px 0 0 !important;
            font-weight: 700 !important;
            font-size: 12px !important;
            /* z-index removed - not supported in PyQt5 */
        }

        /* 非激活Tab的悬停效果 */
        ads--CDockWidgetTab:hover:not(:selected) {
            border-color: #58a6ff;
            color: #58a6ff;
        }

        /* 确保非选中Tab保持原始边框 */
        ads--CDockWidgetTab:not(:selected) {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #21262d, stop:1 #161b22) !important;
            color: #f0f6fc !important;
            border: 2px solid #30363d !important;
            border-bottom: none !important;
            /* box-shadow removed - not supported in PyQt5 */
            /* z-index removed - not supported in PyQt5 */
        }

        /* 停靠窗口内容区域 */
        ads--CDockAreaWidget {
            background-color: #0d1117;
            border: 2px solid #30363d;
            border-radius: 10px;
        }

        /* 停靠窗口标题栏容器 */
        ads--CDockAreaTitleBar {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #21262d, stop:1 #161b22);
            border: none;
            border-radius: 8px 8px 0 0;
            padding: 2px;
            margin: 0;
            min-height: 32px;
        }

        /* 激活的dock area标题栏 */
        ads--CDockAreaTitleBar[focused="true"] {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #1f6feb, stop:1 #0969da);
            border: 2px solid #388bfd;
            border-bottom: none;
            /* box-shadow removed - not supported in PyQt5 */
        }

        /* 基础Tab样式 - 保持原始外观 */
        QWidget[class="ads::CDockWidgetTab"] {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #21262d, stop:1 #161b22) !important;
            color: #f0f6fc !important;
            border: 2px solid #30363d !important;
            /* box-shadow removed - not supported in PyQt5 */
            /* transform removed - not supported in PyQt5 */
        }

        /* 仅激活Tab的蓝色边框高亮 */
        QWidget[class="ads::CDockWidgetTab"][active="true"],
        QWidget[class="ads::CDockWidgetTab"][selected="true"] {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #21262d, stop:1 #161b22) !important;
            color: #ffffff !important;
            border-top: 3px solid #1f6feb !important;
            border-left: 3px solid #1f6feb !important;
            border-right: 3px solid #1f6feb !important;
            border-bottom: none !important;
            border-radius: 8px 8px 0 0 !important;
            font-weight: bold !important;
            /* z-index removed - not supported in PyQt5 */
        }

        /* Dock Area标题栏保持原始样式 */
        QWidget[class="ads::CDockAreaTitleBar"] {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #21262d, stop:1 #161b22) !important;
            color: #f0f6fc !important;
        }

        /* 更强力的激活Tab蓝色边框 */
        *[class*="CDockWidgetTab"]:checked,
        *[class*="DockWidgetTab"]:checked {
            border: 3px solid #1f6feb !important;
            border-bottom: none !important;
            color: #ffffff !important;
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #21262d, stop:1 #161b22) !important;
        }

        /* 通用的Tab激活状态 */
        QWidget:checked {
            border-color: #1f6feb !important;
        }

        /* 尝试不同的PyQtAds选择器 */
        *[objectName^="ads"] {
            background-color: #161b22;
            color: #f0f6fc;
        }

        /* 更强制的PyQtAds选择器 */
        QWidget[class*="CDockWidget"] {
            background-color: #161b22 !important;
            color: #f0f6fc !important;
        }

        QWidget[class*="CDockArea"] {
            background-color: #161b22 !important;
            color: #f0f6fc !important;
        }

        QLabel[class*="CDockWidget"] {
            background-color: transparent !important;
            color: #f0f6fc !important;
        }

        /* 通用强制覆盖 */
        QWidget[class*="ads"] {
            background-color: #161b22 !important;
            color: #f0f6fc !important;
        }

        QLabel[class*="ads"] {
            background-color: transparent !important;
            color: #f0f6fc !important;
        }

        /* 隐藏所有关闭按钮 */
        QPushButton[text="×"] {
            display: none !important;
            visibility: hidden !important;
            width: 0px !important;
            height: 0px !important;
        }

        /* 通过工具提示隐藏Close Tab按钮 */
        QPushButton[toolTip*="Close"] {
            display: none !important;
            visibility: hidden !important;
            width: 0px !important;
            height: 0px !important;
        }

        /* 隐藏所有可能的关闭相关按钮 */
        QWidget[objectName*="close"] {
            display: none !important;
            visibility: hidden !important;
        }

        QWidget[objectName*="Close"] {
            display: none !important;
            visibility: hidden !important;
        }

        /* 强制隐藏PyQtAds标签页区域的所有按钮 */
        ads--CDockAreaTitleBar QPushButton {
            display: none !important;
            visibility: hidden !important;
            width: 0px !important;
            height: 0px !important;
            max-width: 0px !important;
            max-height: 0px !important;
        }

        /* 隐藏标签页标题区域的按钮 */
        ads--CDockAreaTabBar QPushButton {
            display: none !important;
            visibility: hidden !important;
            width: 0px !important;
            height: 0px !important;
        }

        /* 更强力的通用按钮隐藏 */
        QWidget[class*="ads"] QPushButton {
            display: none !important;
            visibility: hidden !important;
            width: 0px !important;
            height: 0px !important;
        }

        /* 通过属性选择器隐藏所有关闭按钮 */
        *[toolTip="Close Tab"] {
            display: none !important;
            visibility: hidden !important;
            width: 0px !important;
            height: 0px !important;
        }

        /* 隐藏所有可能的关闭图标按钮 */
        QPushButton[icon*="close"], QPushButton[icon*="Close"] {
            display: none !important;
            visibility: hidden !important;
        }

        /* 放大ADSDock功能按钮 - List All Tabs, Detach Group, Close Group */
        ads--CDockAreaTitleBar > QPushButton {
            min-width: 24px !important;
            max-width: 24px !important;
            min-height: 24px !important;
            max-height: 24px !important;
            padding: 4px !important;
            margin: 2px !important;
            font-size: 14px !important;
            font-weight: bold !important;
            border-radius: 4px !important;
            background-color: #21262d !important;
            border: 2px solid #30363d !important;
            color: #f0f6fc !important;
        }

        ads--CDockAreaTitleBar > QPushButton:hover {
            background-color: #1f6feb !important;
            border-color: #388bfd !important;
            color: #ffffff !important;
            /* box-shadow removed - not supported in PyQt5 */
        }

        ads--CDockAreaTitleBar > QPushButton:pressed {
            background-color: #0969da !important;
            border-color: #1f6feb !important;
            color: #ffffff !important;
        }

        /* 通过工具提示识别特定按钮并放大 */
        QPushButton[toolTip*="List All Tabs"] {
            min-width: 26px !important;
            max-width: 26px !important;
            min-height: 26px !important;
            max-height: 26px !important;
            padding: 5px !important;
            margin: 3px !important;
            font-size: 16px !important;
            background-color: #21262d !important;
            border: 2px solid #30363d !important;
            border-radius: 5px !important;
            color: #58a6ff !important;
        }

        QPushButton[toolTip*="Detach Group"] {
            min-width: 26px !important;
            max-width: 26px !important;
            min-height: 26px !important;
            max-height: 26px !important;
            padding: 5px !important;
            margin: 3px !important;
            font-size: 16px !important;
            background-color: #21262d !important;
            border: 2px solid #30363d !important;
            border-radius: 5px !important;
            color: #fd7e14 !important;
        }

        QPushButton[toolTip*="Close Group"] {
            min-width: 26px !important;
            max-width: 26px !important;
            min-height: 26px !important;
            max-height: 26px !important;
            padding: 5px !important;
            margin: 3px !important;
            font-size: 16px !important;
            background-color: #21262d !important;
            border: 2px solid #30363d !important;
            border-radius: 5px !important;
            color: #f85149 !important;
        }

        /* 悬停效果 */
        QPushButton[toolTip*="List All Tabs"]:hover {
            background-color: #1f6feb !important;
            border-color: #388bfd !important;
            color: #ffffff !important;
        }

        QPushButton[toolTip*="Detach Group"]:hover {
            background-color: #fd7e14 !important;
            border-color: #fd9843 !important;
            color: #ffffff !important;
        }

        QPushButton[toolTip*="Close Group"]:hover {
            background-color: #da3633 !important;
            border-color: #f85149 !important;
            color: #ffffff !important;
        }

        /* 停靠指示器 */
        ads--CDockOverlay {
            background-color: rgba(31, 111, 235, 0.3);
            border: 3px solid #1f6feb;
            border-radius: 8px;
        }

        /* 停靠指示器图标 */
        ads--CDockOverlayCross {
            background-color: #161b22;
            border: 2px solid #1f6feb;
            border-radius: 15px;
        }

        /* 拆分条样式 */
        ads--CDockSplitter::handle {
            background-color: #30363d;
            border: 1px solid #21262d;
        }

        ads--CDockSplitter::handle:hover {
            background-color: #58a6ff;
            border: 1px solid #1f6feb;
        }

        /* 由于已从源头禁用关闭功能，关闭按钮不会被创建，因此不需要隐藏规则 */

        /* 浮动窗口标题栏 */
        ads--CFloatingDockContainer {
            background-color: #161b22;
            border: 2px solid #30363d;
            border-radius: 10px;
        }

        /* 停靠区域边框高亮 */
        ads--CDockAreaWidget[focused="true"] {
            border: 2px solid #1f6feb;
            /* box-shadow removed - not supported in PyQt5 */
        }

        /* Matplotlib 图表区域优化 */
        QWidget[objectName="matplotlib_canvas"] {
            background-color: #0d1117;
            border: 2px solid #30363d;
            border-radius: 8px;
        }

        /* 自定义按钮颜色覆盖 */
        QPushButton[objectName="demo_btn"] {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #238636, stop:0.5 #1a7f37, stop:1 #1a6228);
            border: 2px solid #2ea043;
            color: #ffffff;
        }

        QPushButton[objectName="demo_btn"]:hover {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #2ea043, stop:0.5 #238636, stop:1 #1f7339);
            border: 2px solid #46954a;
            /* box-shadow removed - not supported in PyQt5 */
        }

        QPushButton[objectName="clear_btn"] {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #fb8500, stop:0.5 #f77f00, stop:1 #f76707);
            border: 2px solid #fd7e14;
            color: #ffffff;
        }

        QPushButton[objectName="clear_btn"]:hover {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                stop:0 #fd7e14, stop:0.5 #fb8500, stop:1 #fd7e14);
            border: 2px solid #fd9843;
            /* box-shadow removed - not supported in PyQt5 */
        }
    """
    app.setStyleSheet(global_dark_theme)

def main():
    """主函数"""
    app = QApplication(sys.argv)
    app.setApplicationName("雷达仿真智能体 - PyQtAds 版")
    app.setApplicationVersion("3.0")

    # 设置应用程序图标
    try:
        icon_path = os.path.join(os.getcwd(), "icons", "radar_icon.ico")
        if os.path.exists(icon_path):
            app.setWindowIcon(QIcon(icon_path))
        else:
            # 备用PNG图标
            png_icon_path = os.path.join(os.getcwd(), "icons", "radar_icon.png")
            if os.path.exists(png_icon_path):
                app.setWindowIcon(QIcon(png_icon_path))
    except Exception as e:
        print(f"设置应用程序图标失败: {e}")

    # 设置应用样式
    app.setStyle('Fusion')

    # 应用全局黑蓝色主题
    apply_global_dark_theme(app)

    # 创建主窗口
    window = RadarSimulationPyQtAdsWindow()
    window.show()

    return app.exec_()

if __name__ == '__main__':
    sys.exit(main())